package com.dc.commons.utils;

import java.io.IOException;
import java.util.List;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.ClassUtils;

import com.google.common.collect.Lists;

public class ClassSearchUtil {

	/** 找到某个包下特定类型的类
	 * @param annotationTypes 类上标记的annotation*/
	@SuppressWarnings("unchecked")
	public static List<Class<?>> getMappingClass(String[] packagesToScan,Class<?>[] annotationTypes) throws Exception {
		List<TypeFilter> filters=Lists.newArrayList();
		for(Class clazz:annotationTypes){
			filters.add( new AnnotationTypeFilter(clazz,false));
		}
		
		List<Class<?>> clazz=Lists.newArrayList();
		String RESOURCE_PATTERN = "**/*.class";
		ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
		if (packagesToScan == null) {
			return clazz;
		}
		for (String pkg : packagesToScan) {
			String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
					+ ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN;
			Resource[] resources = resourcePatternResolver.getResources(pattern);
			MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
			for (Resource resource : resources) {
				if (resource.isReadable()) {
					MetadataReader reader = readerFactory.getMetadataReader(resource);
					String className = reader.getClassMetadata().getClassName();
					if (matchesFilter(reader, readerFactory,filters)) {
						clazz.add(resourcePatternResolver.getClassLoader().loadClass(className));
					}
				}
			}
		}
		return clazz;
	}
	
	
	/** 找到某个包下特定类型的类
	 * @param annotationTypes 类上标记的annotation*/
	public static List<Class<?>> getMappingClassForInterface(String[] packagesToScan,Class<?> Interface) throws Exception {
		
		
		List<Class<?>> classes=Lists.newArrayList();
		String RESOURCE_PATTERN = "**/*.class";
		ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
		if (packagesToScan == null) {
			return classes;
		}
		for (String pkg : packagesToScan) {
			String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
					+ ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN;
			System.out.println(pattern);
			Resource[] resources = resourcePatternResolver.getResources(pattern);
			MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
			for (Resource resource : resources) {
				if (resource.isReadable()) {
					MetadataReader reader = readerFactory.getMetadataReader(resource);
					String className = reader.getClassMetadata().getClassName();
					Class<?> clazz=resourcePatternResolver.getClassLoader().loadClass(className);
					if(Interface.isAssignableFrom(clazz)){
						classes.add(clazz);
					}
					
				}
			}
		}
		return classes;
	}
	
	private static boolean matchesFilter(MetadataReader reader, MetadataReaderFactory readerFactory,List<TypeFilter> filters) throws IOException {
		if (filters != null) {
			for (TypeFilter filter : filters) {
				if (filter.match(reader, readerFactory)) {
					return true;
				}
			}
		}
		return false;
	}
}
